package cn.getech.data.development.controller.offline;

import cn.getech.data.development.config.properties.BdpJobConfig;
import cn.getech.data.development.config.properties.DataDevelopmentConfig;
import cn.getech.data.development.constant.*;
import cn.getech.data.development.entity.*;
import cn.getech.data.development.entity.permission.*;
import cn.getech.data.development.model.res.tableinfo.TableRelationshipRes;
import cn.getech.data.development.model.vo.TableFieldNameInfoVO;
import cn.getech.data.development.service.*;
import cn.getech.data.development.utils.DataPermissionUtil;
import cn.getech.data.development.utils.HdfsUserUtil;
import cn.getech.data.development.utils.HdfsUtil;
import cn.getech.data.development.utils.HiveTableUtil;
import cn.getech.data.intelligence.common.exception.RRException;
import cn.getech.data.intelligence.common.utils.BaseRes;
import cn.getech.data.intelligence.common.utils.DataRes;
import cn.getech.data.intelligence.common.utils.PageUtils;
import cn.getech.data.intelligence.common.utils.R;
import cn.getech.system.center.annotation.SysLog;
import cn.getech.system.center.constant.DefConnectEnum;
import cn.getech.system.center.constant.OperationModulesEnum;
import cn.getech.system.center.constant.OperationTypeEnum;
import cn.getech.system.center.constant.module.ModuleEnum;
import cn.getech.system.center.model.dto.SysUserDto;
import cn.getech.system.center.service.SysUserService;
import cn.getech.system.center.utils.ShiroUtils;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.text.csv.CsvData;
import cn.hutool.core.text.csv.CsvReader;
import cn.hutool.core.text.csv.CsvRow;
import cn.hutool.core.text.csv.CsvUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.apache.http.HttpStatus;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.io.Serializable;
import java.nio.charset.Charset;
import java.sql.SQLException;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 数据表信息
 *
 * @author zenith
 * @Date 2018-09-18 16:38:07
 */
@Slf4j
@Api(tags = "数据表信息")
@RestController
@RequestMapping("/bdp/tableInfo")
public class TableInfoController {

    @Autowired
    private TableInfoService tableInfoService;
    @Autowired
    private TableFieldInfoService tableFieldInfoService;

    @Autowired
    private ProcTableService procTableService;
    @Autowired
    private ProcUserService procUserService;

    @Autowired
    private TableRelationService tableRelationService;


    @Autowired
    private DataDevelopmentConfig hiveConfig;

    @Autowired
    private BdpJobConfig bdpJobConfig;

    @Autowired
    private JobInfoService jobInfoService;

    @Autowired
    private SysUserService sysUserService;

    @Autowired
    private IAllPermissionConfigService iAllPermissionConfigService;

    @Autowired
    private HdfsUserUtil hdfsUserUtil;

    @Autowired
    private RangerDataService rangerDataService;

    @Autowired
    private DataPermissionService dataPermissionService;

    @Autowired
    private TableRelationshipService tableRelationshipService;

    @Autowired
    private ConfConnectService confConnectService;

    @Autowired
    private IDataAssetsModelService iDataAssetsModelService;


    /**
     * 验证用户下是否有仓库表
     */
    @ApiOperation("验证用户下是否有仓库表")
    @PostMapping("/cheackTableByUserId/{userId}")
    public R cheackTableByUserId(@PathVariable("userId") Long userId) {
        tableInfoService.selectByUserId(userId);
        return R.ok();
    }

    /**
     * 获取获取数据仓库的创建人信息，用于前端筛选
     */
    @ApiOperation("获取获取数据仓库的创建人信息")
    @GetMapping("/userList")//  /bdp/tableInfo/userList
    @SysLog(value = "获取获取数据仓库的创建人信息", type = OperationTypeEnum.SELECTCODE, modulesType = OperationModulesEnum.TABLEMODELCODE)
    public R userList() {
        Map<String, Object> params = Maps.newHashMap();
        List<TableInfo> list = tableInfoService.selectList(params);
        fillTableInfo(list);
        List<Map<String, Object>> userList = Lists.newArrayList();
        Set<Integer> userIdSet = Sets.newHashSet();
        for (TableInfo tableInfo : list) {
            if (tableInfo.getCreatePer() == null
                    || StringUtils.isEmpty(tableInfo.getCreatePerName())) {
                continue;
            }
            if (!userIdSet.contains(tableInfo.getCreatePer())) {
                Map<String, Object> user = Maps.newHashMap();
                user.put("userId", tableInfo.getCreatePer());
                user.put("userName", tableInfo.getCreatePerName());
                userList.add(user);
                userIdSet.add(tableInfo.getCreatePer());
            }
        }
        return R.okWithData(userList);
    }

    @ApiOperation("获取未关联的数据表信息列表")
    @GetMapping("/listNoRelation")
    public R listNoRelation(@RequestParam Map<String, Object> params) {
        params.put("create_per", ShiroUtils.getUserId().intValue());
        params.put("sidx", "a.create_time");
        params.put("order", "desc");
        PageUtils page = tableInfoService.listNoRelation(params);
        return R.okWithPage(page);
    }


    /**
     * 获取已关联的数据表信息列表
     */
    @ApiOperation("获取已关联的数据表信息列表")
    @PostMapping("/list")
    public R list(@ApiParam(value = "{'table_name':'test','db_name':'test','jobId':1,'proc_id':1}")
                  @RequestBody Map<String, Object> params) {
//        params.put("create_per",ShiroUtils.getUserId().intValue());
        params.put("sidx", "a.create_time");
        params.put("order", "desc");
        //验证参数
//        if(null == params.get("db_name")){
//            throw new RRException(String.format(BizExceptionEnum.PARAM_FAIL_ERROR.getMessage(),"数据库名称不能为空"));
//        }
        if (null == params.get("proc_id")) {
            if (null == params.get("jobId")) {
                throw new RRException(DataDevelopmentBizExceptionEnum.TABLE_NO_JOBID_OR_PROCID.getMessage());
            }
            //通过job_id查询到对应的job信息
            JobInfo jobInfo = jobInfoService.getById((Serializable) params.get("jobId"));
            if (null == jobInfo) {
                throw new RRException(DataDevelopmentBizExceptionEnum.TABLE_NO_JOBID_OR_PROCID.getMessage());
            }
            params.put("proc_id", jobInfo.getProcId());
        }

        //如果传入page limit 则分页否则全部返回
        if (params.containsKey("page") && params.containsKey("limit")) {
            PageUtils <TableInfo> page = tableInfoService.selectListPage(params);
            fillTableInfo(page.getList());
            return R.okWithPage(page);
        } else {
            List<TableInfo> list = tableInfoService.selectList(params);

            if(params.get("typeId") != null && JobType.ALGORITHM.getCode() == Integer.parseInt(params.get("typeId").toString())){
                //当算法开发页面掉此接口时,选择预测数据需要过滤预测数据是否含有x字段及主键字段(flagId=1);
                if(params.get("modelId")!="" && params.get("modelId")!= null
                        && Integer.parseInt(params.get("flagId").toString()) == 1){
                    list = iDataAssetsModelService.pdTableExistsXfieldAndPrimaryKey(list, Integer.valueOf(params.get("modelId").toString()));
                }
            }
            fillTableInfo(list);
            return R.okWithData(list);
        }
    }


    /**
     * 获取已关联的数据表信息列表
     */
    @ApiOperation("获取已关联的数据表信息列表")
    @PostMapping("/listTableByStorageEngine")
    public R listTableByStorageEngine(@ApiParam(value = "{'table_name':'test','db_name':'test','jobId':1,'proc_id':1,'storage_engine_type':1}")
                                      @RequestBody Map<String, Object> params) {
        params.put("sidx", "id");
        params.put("order", "desc");
        if (null == params.get("proc_id")) {
            if (null == params.get("jobId")) {
                throw new RRException(DataDevelopmentBizExceptionEnum.TABLE_NO_JOBID_OR_PROCID.getMessage());
            }
            //通过job_id查询到对应的job信息
            JobInfo jobInfo = jobInfoService.getById((Serializable) params.get("jobId"));
            if (null == jobInfo) {
                throw new RRException(DataDevelopmentBizExceptionEnum.TABLE_NO_JOBID_OR_PROCID.getMessage());
            }
            params.put("proc_id", jobInfo.getProcId());
        }

        List<TableInfo> list = tableInfoService.listTableByStorageEngine(params);
        fillTableInfo(list);
        return R.okWithData(list);
    }

    private void fillTableInfo(List<TableInfo> tableInfoList) {
        List<SysUserDto> userList = sysUserService.listAllUsers();
        Map<Long, String> userMap = userList.stream().collect(
                Collectors.toMap(SysUserDto::getUserId, SysUserDto::getUsername));
        for (TableInfo tableInfo : tableInfoList) {
            //添加创建用户的信息
            Long userId = Long.valueOf(tableInfo.getCreatePer());
            tableInfo.setCreatePerName(userMap.get(userId));
        }
    }

    /**
     * 获取数据表信息列表
     */
    @ApiOperation("获取数据表信息列表根据角色")
    @GetMapping("/listByRole")
    @SysLog(value = "获取数据表信息列表根据角色", type = OperationTypeEnum.SELECTCODE, modulesType = OperationModulesEnum.TABLEMODELCODE)
    public R listByRole(@ApiParam(value = "{'table_name':'test','db_name':'test'}") @RequestParam Map<String, Object> params) {
        params.put("sidx", "id");
        params.put("order", "desc");
        if (params.get("role_id") == null) {
            return R.error("请选择角色!");
        }
        PageUtils page = tableInfoService.listPageByRole(params);
        return R.okWithPage(page);
    }

    /**
     * 获取数据表信息列表
     */
    @ApiOperation("获取数据表信息列表根据租户")
    @GetMapping("/listByTenant")
    @SysLog(value = "获取数据表信息列表根据租户", type = OperationTypeEnum.SELECTCODE, modulesType = OperationModulesEnum.TABLEMODELCODE)
    public R listByTenant(@ApiParam(value = "{'table_name':'test','db_name':'test'}") @RequestParam Map<String, Object> params) {
        params.put("sidx", "id");
        params.put("order", "desc");
        if (params.get("tenant_id") == null) {
            return R.error("请选择租户!");
        }
        PageUtils page = tableInfoService.listPageByTenant(params);
        return R.okWithPage(page);
    }

    /**
     * 保存数据仓库表的权限信息
     */
    @ApiOperation("保存数据仓库表的权限信息")
    @PostMapping("/savePermission")
    @SysLog(value = "离线数仓授权", type = OperationTypeEnum.APPROVECODE, modulesType = OperationModulesEnum.TABLEMODELCODE,platformModuleType = ModuleEnum.AUTH_MANAGER_MODULE_CODE)
    public R savePermission(@RequestBody List<TableInfoPermission> dataList) {
//        if (CollectionUtil.isNotEmpty(dataList)) {
//            List<Integer> dataIds = DataPermissionUtil.getDataIds(ShiroUtils.getUserId().intValue(),
//                    PermissionTypeEnum.STORE.getType(),
//                    PermissionTypeEnum.ASSIGN.getType());
//            List<Integer> fieldIds = DataPermissionUtil.getDataIds(ShiroUtils.getUserId().intValue(),
//                    PermissionTypeEnum.STORE_FILED.getType(),
//                    PermissionTypeEnum.ASSIGN.getType());
//            List<Integer> saveTableIds = dataList.stream().map(i -> i.getDataId()).collect(Collectors.toList());
//            List<Integer> saveFieldIds=new ArrayList<>();
//            for(TableInfoPermission realTablePermission:dataList){
//                if(CollectionUtil.isNotEmpty(realTablePermission.getTableFieldInfos())){
//                    List<TableFieldInfoPermission> fieldInfoPermissions=realTablePermission.getTableFieldInfos();
//                    saveFieldIds.addAll(fieldInfoPermissions.stream().map(i->i.getDataId()).collect(Collectors.toList()));
//                }
//            }
//            if (!dataIds.containsAll(saveTableIds)|| !fieldIds.containsAll(saveFieldIds)) {
//                return R.error("存在无权限数据，请刷新重试");
//            }
//        }
        tableInfoService.savePermission(dataList);
        return R.ok();
    }

    /**
     * 保存数据仓库表的权限信息
     */
    @ApiOperation("保存数据仓库表的权限信息(租户)")
    @PostMapping("/saveTenantPermission")
    @SysLog(value = "离线数仓授权根据租户", type = OperationTypeEnum.APPROVECODE, modulesType = OperationModulesEnum.TABLEMODELCODE,platformModuleType = ModuleEnum.AUTH_MANAGER_MODULE_CODE)
    public R saveTenantPermission(@RequestBody List<TenantTableInfoPermission> dataList) {
        tableInfoService.saveTenantPermission(dataList);
        return R.ok();
    }
    /**
     * 获取数据表树列表
     */
    @ApiOperation("获取数据表树列表")
    @GetMapping("/listTree")
    public R listTree(@ApiParam(value = "{'table_name':'test','db_name':'test','proc_id':1}") @RequestParam Map<String, Object> params) {
        params.put("sidx", "id");
        params.put("order", "desc");
        //token失效
        Long userId = ShiroUtils.getUserId();
        if (null == userId) {
            throw new RRException("invalid token", HttpStatus.SC_UNAUTHORIZED);
        }
        if (params.get("proc_id") != null) {
            params.put("procId", params.get("proc_id"));
            params.remove("proc_id");
        }
        JSONArray array = tableInfoService.roleAndPermission(params, userId);
        return R.okWithPage(array);
    }


    /**
     * 获取数据表树列表(不含字段)
     */
    @ApiOperation("获取数据表树列表(不含字段)")
    @GetMapping("/listTreeNotField")
    public R listTreeNotField(@ApiParam(value = "{'table_name':'test','db_name':'test','proc_id':1}") @RequestParam Map<String, Object> params) {

        if (params.get("proc_id") != null) {
            params.put("procId", params.get("proc_id"));
            params.remove("proc_id");
        }
        //token失效
        Long userId = ShiroUtils.getUserId();
        if (null == userId) {
            throw new RRException("invalid token", HttpStatus.SC_UNAUTHORIZED);
        }
        params.put("sidx", "id");
        params.put("order", "desc");
        JSONArray array = tableInfoService.listTreeNotField(params, userId);
        return R.okWithPage(array);
    }



    /**
     * 获取数据表树列表单个表的字段
     */
    @ApiOperation("获取数据表树列表单个表的字段")
    @GetMapping("/listTreeField/{tableId}")
    public R listTreeField(@ApiParam(value = "表id")@PathVariable("tableId") Integer tableId) {

        //token失效
        Long userId = ShiroUtils.getUserId();
        if (null == userId) {
            throw new RRException("无效的token", HttpStatus.SC_UNAUTHORIZED);
        }
        JSONArray array = tableInfoService.listTreeField(tableId,userId);
        return R.okWithPage(array);
    }


    /**
     * 获取数据表树项目列表
     */
    @ApiOperation("获取数据表树列表")
    @GetMapping("/search/project")
    public R searchProject() {
        Long userId = ShiroUtils.getUserId();
        List<Map<String,Object>> projectList = tableInfoService.searchProjectList(userId);
        return R.okWithData(projectList);
    }

    @Resource
    private RestHighLevelClient client;

    @Value("${elasticsearch.fieldIndexName}")
    private String fieldIndexName;

    /**
     * 删除数据表信息
     */
    @ApiOperation("删除数据表信息")
    @SysLog(value="删除数据表信息",type= OperationTypeEnum.DELETECODE,
            modulesType = OperationModulesEnum.TABLEMODELCODE,platformModuleType = ModuleEnum.DATA_MAP_MODULE_CODE)
    @PostMapping("/delete")
    public R delete(@ApiParam(value = "{'id':1}") @RequestBody TableInfo param) {
        long startTime = new Date().getTime();
        if (!tableInfoService.checkExistById(param.getId())) {
            throw new RRException(DataDevelopmentBizExceptionEnum.TABLE_NOT_EXIST.getMessage());
        }
        if (tableInfoService.checkIfRef(param.getId())) {
            throw new RRException(DataDevelopmentBizExceptionEnum.TABLE_DEPEND_PROC.getMessage());
        }

        if (!tableInfoService.checkPermission(param.getId()) && //不是自己创建的数据 才做权限校验
                !dataPermissionService.checkDataPermission(param.getId(),
                        PermissionTypeEnum.STORE.getType(), PermissionTypeEnum.DELETE.getType())) {
            throw new RRException(DataDevelopmentBizExceptionEnum.DELETE_NO_PERMISSION.getMessage());
        }
        //验证分析任务是否关联
        tableInfoService.checkedAnalysisInfo(param.getId(), 1);
        TableInfo tableInfo = tableInfoService.getById(param.getId());
        String dbName = tableInfo.getDbName();
        String tableName = tableInfo.getTableName();
        HiveTableUtil hiveTableUtil;
        if (StorageEngineEnum.KUDU.getCode().equals(tableInfo.getStoreEngine())) {
            hiveTableUtil = new HiveTableUtil(hiveConfig.getKuduJdbcUrl(), dbName, "hdfs", "hdfs");
        } else {
            hiveTableUtil = new HiveTableUtil(hiveConfig.getHiveserverurl(), dbName, "hdfs", "hdfs");
        }
        //删除es中对应的数据表&字段
        BulkRequest request = new BulkRequest();
        if (param.getId()!=null) {
            request.add(new DeleteRequest().index(fieldIndexName).id(param.getId().toString()));
            BulkResponse delete = null;
            try {
                delete = this.client.bulk(request, RequestOptions.DEFAULT);
            } catch (IOException e) {
                e.printStackTrace();
            }
            log.info("-------"+delete.status());
        }
        try {
            List<TableRegisterEntity> registerEntityList = new ArrayList<>();
            if (tableInfoService.deleteDbTable(tableInfo, registerEntityList, true)) {
                hiveTableUtil.dropTable(tableName);
                hiveTableUtil.close();
                rangerDataService.deleteRangerPloicyByTableId(tableInfo.getId());
                tableInfoService.addRegisterDelete(startTime, registerEntityList, null);
                return R.ok();
            } else {
                return R.error("删除失败");
            }
        } catch (SQLException e) {
            hiveTableUtil.close();
            throw new RRException(e.getMessage(), 500);
        }

    }

    /**
     * 批量删除表的数据和元数据
     */
    @ApiOperation("批量删除表的数据和元数据")
    @SysLog(value="批量删除表的数据和元数据",type= OperationTypeEnum.DELETECODE,
            modulesType = OperationModulesEnum.TABLEMODELCODE,platformModuleType = ModuleEnum.DATA_MAP_MODULE_CODE)
    @PostMapping("/batchDrop")
    public R batchDrop(@ApiParam(value = "{'id':1}") @RequestBody List<Integer> ids) {
        long startTime = new Date().getTime();
        if (CollectionUtil.isNotEmpty(ids)) {
            List<TableRegisterEntity> registerEntityList = new ArrayList<>();
            for (Integer id : ids) {
                TableInfo tableInfo = tableInfoService.getById(id);
                if (tableInfo != null) {
                    String dbName = tableInfo.getDbName();
                    String tableName = tableInfo.getTableName();
                    HiveTableUtil hiveTableUtil;
                    if (StorageEngineEnum.KUDU.getCode().equals(tableInfo.getStoreEngine())) {
                        hiveTableUtil = new HiveTableUtil(hiveConfig.getKuduJdbcUrl(), dbName, "hdfs", "hdfs");
                    } else {
                        hiveTableUtil = new HiveTableUtil(hiveConfig.getHiveserverurl(), dbName, "hdfs", "hdfs");
                    }
                    //删除数据库表和hive的表的结构
                    try {

                        if (tableInfoService.deleteDbTable(tableInfo, registerEntityList, true)) {
                            hiveTableUtil.dropTable(tableName);
                            hiveTableUtil.close();
                            try {
                                rangerDataService.deleteRangerPloicyByTableId(tableInfo.getId());
                            } catch (Exception e) {
                                log.warn("删除ranger策略错误 表id{}", tableInfo.getId());
                            }
                        }
                    } catch (SQLException e) {
                        hiveTableUtil.close();
                        throw new RRException(e.getMessage(), 500);
                    }
                    //删除数据
                    HdfsUtil hdfsUtil = null;
                    try {
                        hdfsUtil = new HdfsUtil(bdpJobConfig);
                        hdfsUtil.delete(HiveTableUtil.genTableLocation(dbName, tableName));
                    } catch (Exception e) {
                        throw new RRException(e.getMessage(), 500);
                    }finally {
                        if(null != hdfsUtil){
                            hdfsUtil.close();
                        }
                    }
                }
            }

            //添加删除表到元数据
            tableInfoService.addRegisterDelete(startTime, registerEntityList, null);
        }
        return R.ok();
    }


    /**
     * 删除表的数据和元数据
     */
    @ApiOperation("删除表的数据和元数据")
    @SysLog(value="删除表的数据和元数据",type= OperationTypeEnum.DELETECODE,
            modulesType = OperationModulesEnum.TABLEMODELCODE,platformModuleType = ModuleEnum.DATA_MAP_MODULE_CODE)
    @PostMapping("/drop")
    public R drop(@ApiParam(value = "{'id':1}") @RequestBody TableInfo param) {
        long startTime = new Date().getTime();

        TableInfo tableInfo = tableInfoService.getById(param.getId());
        String dbName = tableInfo.getDbName();
        String tableName = tableInfo.getTableName();
        if (!tableInfoService.checkPermission(param.getId()) && //不是自己创建的数据 才做权限校验
                !dataPermissionService.checkDataPermission(param.getId(),
                        PermissionTypeEnum.STORE.getType(), PermissionTypeEnum.DELETE.getType())) {
            throw new RRException(DataDevelopmentBizExceptionEnum.DELETE_NO_PERMISSION.getMessage());
        }

        //删除数据库表和hive,es的表的结构
        delete(param);
        //删除数据
        HdfsUtil hdfsUtil = null;
        try {
            hdfsUtil = new HdfsUtil(bdpJobConfig);
            hdfsUtil.delete(HiveTableUtil.genTableLocation(dbName, tableName));
            //删除离线表对应相关的质量报告信息
            tableInfoService.deleteDataQualityInfo(dbName,tableName);
            return R.ok();
        } catch (Exception e) {
            throw new RRException(e.getMessage(), 500);
        }finally {
            if(null != hdfsUtil){
                hdfsUtil.close();
            }
        }
    }


    /**
     * 详情
     */
    @ApiOperation("详情")
    @SysLog(value = "获取数据仓库表详情", type = OperationTypeEnum.SELECTCODE, modulesType = OperationModulesEnum.TABLEMODELCODE,platformModuleType = ModuleEnum.DATA_MAP_MODULE_CODE)
    @GetMapping("/info/{id}")
    //    @RequiresPermissions("bdp:tableInfo:info")
    public DataRes<TableInfo> info(@PathVariable("id") Integer id, Integer page, Integer limit, Integer flag) {
        if (!tableInfoService.checkExistById(id)) {
            throw new RRException(DataDevelopmentBizExceptionEnum.TABLE_NOT_EXIST.getMessage());
        }
        TableInfo tableInfo = tableInfoService.getDetailById(id);
        if (tableInfo != null) {
            //填充表的所属目录
            List<String> categoryIds = tableInfoService.selectCategoryIdsByTableId(tableInfo.getId());
            tableInfo.setCateGoryIdsList(categoryIds);
            page = page == null || page == 0 ? 1 : page;
            limit = limit == null || limit == 0 ? 10 : limit;
            IPage<TableFieldInfo> dataPage = new Page<>(page, limit);
            if (YesOrNoEnum.YES.getValue().equals(flag)) {//不需要权限过滤
                QueryWrapper<TableFieldInfo> wrapper = new QueryWrapper<>();
                wrapper.eq("table_id", id);
                wrapper.orderByAsc("field_order", "is_partition");
                dataPage = tableFieldInfoService.page(dataPage, wrapper);
                tableInfo.setTableFieldInfos(dataPage.getRecords());
            } else {
                dataPage = tableFieldInfoService.page(dataPage, id);
                tableInfo.setTableFieldInfos(dataPage.getRecords());
            }

            fillRelation(tableInfo);
        }
        return BaseRes.okWithData(tableInfo);
    }

    private void fillRelation(TableInfo tableInfo) {
        if (CollectionUtil.isNotEmpty(tableInfo.getTableFieldInfos())) {
            QueryWrapper<TableRelationshipEntity> param = new QueryWrapper<TableRelationshipEntity>()
                    .eq("source_table_id", tableInfo.getId())
                    .eq("data_type",YesOrNoEnum.NO.getValue())
                    ;
            if (tableInfo.getMetaId() != null) {
                param.or().eq("source_coll_table_id",tableInfo.getMetaId())
                     .eq("data_type",YesOrNoEnum.NO.getValue())
                ;
            }
            List<TableRelationshipEntity> list = tableRelationshipService.list(param);

            if (CollectionUtil.isEmpty(list))
                return;
            List<Integer> sourceList = list.stream().map(TableRelationshipEntity::getRelationSourceId).distinct().collect(Collectors.toList());
            List<ConfConnect> confConnectList = confConnectService.list(new QueryWrapper<ConfConnect>().in("id", sourceList));
            for (TableFieldInfo fieldInfo : tableInfo.getTableFieldInfos()) {
                List<TableRelationshipEntity> collect = list.stream().filter(t -> fieldInfo.getFieldName().equals(t.getSourceFieldName())).collect(Collectors.toList());
                fieldInfo.setRelationshipes(collect);
                if (CollectionUtil.isNotEmpty(collect)) {
                    for (TableRelationshipEntity tableRelationshipEntity : collect) {
                        Optional<ConfConnect> first = confConnectList.stream().filter(
                                c -> c.getId().equals(tableRelationshipEntity.getRelationSourceId())).findFirst();
                        if (first.isPresent()) {
                            tableRelationshipEntity.setRelationSourceName(first.get().getName());
                        } else {
                            Integer sourceId = tableRelationshipEntity.getRelationSourceId();
                            String sourceName = "默认数据源";
                            if (DefConnectEnum.HIVE.getCode().equals(sourceId)) {
                                sourceName = DefConnectEnum.HIVE.getName();
                            } else if (DefConnectEnum.IMPALA.getCode().equals(sourceId)) {
                                sourceName = DefConnectEnum.IMPALA.getName();
                            } else if (DefConnectEnum.KAFKA.getCode().equals(sourceId) ) {
                                sourceName = DefConnectEnum.KAFKA.getName();
                            } else if (DefConnectEnum.OTHER.getCode().equals(sourceId)) {
                                sourceName = DefConnectEnum.OTHER.getName();
                            }
                            tableRelationshipEntity.setRelationSourceName(sourceName);
                        }
                    }
                }
            }
        }
    }


    /**
     * 获取数据仓库表字段
     */
    @ApiOperation("获取数据仓库表字段")
    @SysLog(value = "获取数据仓库表字段", type = OperationTypeEnum.SELECTCODE, modulesType = OperationModulesEnum.TABLEMODELCODE,platformModuleType = ModuleEnum.DATA_MAP_MODULE_CODE)
    @GetMapping("/getFileds/{id}")
    //    @RequiresPermissions("bdp:tableInfo:info")
    public R getFileds(@PathVariable("id") Integer id) {
        if (!tableInfoService.checkExistById(id)) {
            throw new RRException(DataDevelopmentBizExceptionEnum.TABLE_NOT_EXIST.getMessage());
        }
        List<TableFieldInfo> tableFieldInfos = tableFieldInfoService.list(new QueryWrapper<TableFieldInfo>().eq("table_id", id).orderByAsc("field_order", "is_partition"));
        List<TableFieldNameInfoVO> tableFieldInfoVOS = new ArrayList<>();
        tableFieldInfos.forEach(t -> {
            TableFieldNameInfoVO tableFieldNameInfoVO = new TableFieldNameInfoVO();
            BeanUtils.copyProperties(t, tableFieldNameInfoVO);
            tableFieldInfoVOS.add(tableFieldNameInfoVO);
        });

        return R.okWithData(tableFieldInfoVOS);
    }



    /**
     * 通过表id和字段类型，获取数据仓库表字段
     */
    @ApiOperation("通过表id和字段类型，获取数据仓库表字段")
    @SysLog(value = "通过表id和字段类型，获取数据仓库表字段", type = OperationTypeEnum.SELECTCODE, modulesType = OperationModulesEnum.TABLEMODELCODE,platformModuleType = ModuleEnum.DATA_MAP_MODULE_CODE)
    @GetMapping("/getFileds/{tableId}/{filedType}")
    //    @RequiresPermissions("bdp:tableInfo:info")
    public R getFileds(@PathVariable("tableId") Integer tableId, @PathVariable("filedType") Integer filedType) {
        if (!tableInfoService.checkExistById(tableId)) {
            throw new RRException(DataDevelopmentBizExceptionEnum.TABLE_NOT_EXIST.getMessage());
        }
        List<TableFieldInfo> tableFieldInfos = tableFieldInfoService.getFileds(new QueryWrapper<TableFieldInfo>(),tableId,filedType);
        List<TableFieldNameInfoVO> tableFieldInfoVOS = new ArrayList<>();
        tableFieldInfos.forEach(t -> {
            TableFieldNameInfoVO tableFieldNameInfoVO = new TableFieldNameInfoVO();
            BeanUtils.copyProperties(t, tableFieldNameInfoVO);
            tableFieldInfoVOS.add(tableFieldNameInfoVO);
        });

        return R.okWithData(tableFieldInfoVOS);
    }

    /**
     * 获取所有的配置类别
     */
    @ApiOperation("获取所有的数据库名称")
    @GetMapping("/listDbs")
    public R listDbs() {
        List<String> list=Lists.newArrayList();
        for (DBTypeEnum value : DBTypeEnum.values()) {
            list.add(value.getName());
        }
        list.sort(String::compareTo);
        return R.okWithData(list);
    }


    @ApiOperation("获取所有的数据库名称和表名称")
    @GetMapping("/listDbsAndTables")
    public R listDbsAndTables(@RequestParam(value = "procId", required = false) Integer procId) {
        //是否是自己可以看到的对应的库和表
        JSONArray listRest = tableInfoService.listDbsAndTables(procId);
        return R.okWithData(listRest);
    }

    /**
     * 获取所有的数据格式名称
     */
    @ApiOperation("获取所有的数据格式名称")
    @GetMapping("/listDataFormats")
    public R listDataFormats(@RequestParam(required = false) Integer type) {
        return R.okWithData(DataFormat.getValues(type));
    }

    /**
     * 获取所有的数据格式名称
     */
    @ApiOperation("获取所有的分隔符的名称")
    @GetMapping("/listDelimitFormats")
    public R listDelimitFormats(@RequestParam(required = false ,defaultValue = "1") Integer type) {
        List<JSONObject> data = new ArrayList<>();
        for (DelimitFormat e : DelimitFormat.values()
        ) {
            if (type != null && type == 2) { //实时表不支持 分号
                if (e.getId() == 2) {
                    continue;
                }
            }
            JSONObject obj = new JSONObject();
            obj.put("id", e.getId());
            obj.put("name", e.getName());
            data.add(obj);
        }
        return R.okWithData(data);
    }

    /**
     * 获取所有的数据类型名称  1 hive 2 kudu
     */
    @ApiOperation("获取所有的数据类型名称")
    @GetMapping("/listDataTypes")
    public R listDataTypes(@RequestParam(required = false,defaultValue = "3") Integer type) {
        if (StorageEngineEnum.KUDU.getCode().equals(type)) {
            return R.okWithData(TableKuduType.values());
        }
        if (StorageEngineEnum.HIVE.getCode().equals(type)) {
            return R.okWithData(HiveTableDataType.getValues());
        }
        return R.okWithData(TableDataType.values());
    }

    /**
     * 项目关联数据表
     */
    @ApiOperation("项目关联数据表")
    @SysLog(value="项目关联数据表操作",type= OperationTypeEnum.RELATIONCODE,
            modulesType = OperationModulesEnum.PROCMODECODE,platformModuleType = ModuleEnum.PROJECT_LIST_MODULE_CODE)
    @PostMapping("/procRelation")
    public R procRelation(@ApiParam(value = "{'procId':1,'tableId':[1,1]}") @RequestBody Map<String, Object> params) {
        if (!checkRelation(params)) {
            return R.error("请选择需要关联的表");
        }
        try {
            Integer procId = Integer.parseInt(params.get("procId").toString());
            if(!procUserService.checkViewPermission(procId)){
                throw new RRException(DataDevelopmentBizExceptionEnum.PROCINFO_PERMISSIOIN.getMessage());
            }
            Integer tableType = 1;
            if (params.get("tableType") != null) {
                tableType = Integer.parseInt(params.get("tableType").toString());
            }
            List<Integer> tableIdList = (List<Integer>) params.get("tableId");
            QueryWrapper<ProcTable> remove = new QueryWrapper<ProcTable>()
                    .eq("proc_id", procId).in("table_id", tableIdList)
                    .eq("table_type", tableType);
            procTableService.remove(remove);
            for (Integer tableId : tableIdList
            ) {
                ProcTable procTable = new ProcTable();
                procTable.setProcId(procId);
                procTable.setTableId(tableId);
                procTable.setTableType(tableType);
                procTableService.save(procTable);
            }
            return R.ok();
        } catch (Exception ex) {
            log.error("关联异常:",ex);
            return R.error(DataDevelopmentBizExceptionEnum.SERVER_ERROR.getMessage());
        }
    }

    /**
     * 项目取消关联数据源
     */
    @ApiOperation("项目取消关联数据表 项目编号：procId,数据表编号 tableId ")
    @SysLog(value="项目取消关联数据表操作",type= OperationTypeEnum.DISASSOCIATIONCODE,
            modulesType = OperationModulesEnum.PROCMODECODE,platformModuleType = ModuleEnum.PROJECT_LIST_MODULE_CODE)
    @PostMapping("/procUnRelation")
    public R procUnRelation(@ApiParam(value = "{'procId':1,'tableId':1}") @RequestBody Map<String, Object> params) {
        if (!checkRelation(params)) {
            return R.error("请选择需要取消关联的表");
        }
        Integer proc_id = Integer.parseInt(params.get("procId").toString());
        Integer table_id = Integer.parseInt(params.get("tableId").toString());
        Integer tableType = StoreTableType.OFFLINE.getCode();
        if (params.get("tableType") != null) {
            tableType = Integer.parseInt(params.get("tableType").toString());
        }
        if (!procTableService.checkTaskRelation(proc_id, table_id, tableType)) {
            return R.error("当前表已被任务引用，不可取消关联");
        }
        if(!procUserService.checkViewPermission(proc_id)){
            throw new RRException(DataDevelopmentBizExceptionEnum.PROCINFO_PERMISSIOIN.getMessage());
        }
        procTableService.remove(new QueryWrapper<ProcTable>().eq("proc_id", proc_id)
                .eq("table_id", table_id)
                .eq("table_type", tableType));
        return R.ok();
    }

    private boolean checkRelation(Map<String, Object> params) {
        return params.size() == 3
                && params.containsKey("procId")
                && params.containsKey("tableType")
                && params.containsKey("tableId");
    }

    /**
     * 验证表当前用户是否有权限查看这个表对应的菜单
     */
    @ApiOperation("验证表当前用户是否有权限查看这个表对应的菜单")
    @GetMapping("/cheackDataPressionMenu/{id}")
    public R cheackDataPressionMenu(@PathVariable("id") Integer id) {
        boolean flage = tableInfoService.cheackDataPressionMenu(id, ShiroUtils.getUserId());
        return R.okWithData(flage);
    }

    /**
     * 验证表当前用户是否有权限查看
     */
    @ApiOperation("验证表当前用户是否有权限查看")
    @GetMapping("/cheackTable/{id}")
    public R cheackTable(@PathVariable("id") Integer id) throws Exception {
        return R.ok();
    }


    /**
     * 数据预览
     */
    @ApiOperation("数据预览")
    @SysLog(value = "数据仓库的数据预览", type = OperationTypeEnum.SELECTCODE, modulesType = OperationModulesEnum.TABLEMODELCODE,platformModuleType = ModuleEnum.DATA_MAP_MODULE_CODE)
    @GetMapping("/dataPreview/{id}/{page}/{limit}")
    public R dataPreview(@PathVariable("id") Integer id, @PathVariable("page") Integer page, @PathVariable("limit") Integer limit, Integer flag) throws Exception {
        TableInfo tableInfo = tableInfoService.getById(id);
        hdfsUserUtil.setRangerUser(ShiroUtils.getUserId());
        if (YesOrNoEnum.YES.getValue().equals(flag)) {//不需要权限过滤
            page = page == null || page == 0 ? 1 : page;
            limit = limit == null || limit == 0 ? 10 : limit;
            IPage<TableFieldInfo> dataPage = new Page<>(page, limit);
            QueryWrapper<TableFieldInfo> wrapper = new QueryWrapper<>();
            wrapper.eq("table_id", id);
            wrapper.orderByAsc("field_order", "is_partition");
            dataPage = tableFieldInfoService.page(dataPage, wrapper);
            tableInfo.setTableFieldInfos(dataPage.getRecords());
        } else {
            List<TableFieldInfo> tableFieldInfos = tableFieldInfoService.list(new QueryWrapper<TableFieldInfo>(), id);
            tableInfo.setTableFieldInfos(tableFieldInfos);
        }
        HiveTableUtil hiveTableUtil;
        //增加数据预览数据脱敏队列
        String queenName= "root.users.datapre";
        if (StorageEngineEnum.KUDU.getCode().equals(tableInfo.getStoreEngine())) {
            hiveTableUtil = new HiveTableUtil(hiveConfig.getKuduJdbcUrl(), queenName,tableInfo.getDbName()
                    , hdfsUserUtil.getRangerUserName(), hdfsUserUtil.getRangerUserPassword());
        } else {
            hiveTableUtil = new HiveTableUtil(hiveConfig.getHiveserverurl(),queenName, tableInfo.getDbName(),
                    hdfsUserUtil.getRangerUserName(), hdfsUserUtil.getRangerUserPassword());
        }
        if (CollectionUtil.isEmpty(tableInfo.getTableFieldInfos())) {
            return R.error("无字段权限,无法预览数据");
        }
        //hive查询结果的分页
        List<String> columnList = tableInfo.getTableFieldInfos().stream().map(TableFieldInfo::getFieldName).collect(Collectors.toList());
        List<JSONObject> list = hiveTableUtil.tableInfoDataPreview(tableInfo, columnList, page, limit);
        int totalCount = 1111110;
        PageUtils pageData = new PageUtils(list, totalCount, limit, page);
        R r = R.okWithPage(pageData);
        //将标题也放进去
        r.put("titleList", columnList);
        return r;
    }


    /**
     * 单字段数据预览
     */
    @ApiOperation("单字段数据预览")
    @SysLog(value = "数据仓库的单字段数据预览", type = OperationTypeEnum.SELECTCODE, modulesType = OperationModulesEnum.TABLEMODELCODE,platformModuleType = ModuleEnum.DATA_MAP_MODULE_CODE)
    @GetMapping("/columnDataPreview/{id}/{fieldId}/{page}/{limit}")
    public R columnDataPreview(@PathVariable("id") Integer id, @PathVariable("fieldId") String fieldId, @PathVariable("page") Integer page, @PathVariable("limit") Integer limit) throws Exception {
        TableInfo tableInfo = tableInfoService.getById(id);
        hdfsUserUtil.setRangerUser(ShiroUtils.getUserId());
        HiveTableUtil hiveTableUtil;
        //增加数据预览数据脱敏队列
        String queenName= "root.users.datapre";
        if (StorageEngineEnum.KUDU.getCode().equals(tableInfo.getStoreEngine())) {
            hiveTableUtil = new HiveTableUtil(hiveConfig.getKuduJdbcUrl(), queenName,tableInfo.getDbName()
                    , hdfsUserUtil.getRangerUserName(), hdfsUserUtil.getRangerUserPassword());
        } else {
            hiveTableUtil = new HiveTableUtil(hiveConfig.getHiveserverurl(),queenName, tableInfo.getDbName(),
                    hdfsUserUtil.getRangerUserName(), hdfsUserUtil.getRangerUserPassword());
        }
//        if (CollectionUtil.isEmpty(tableInfo.getTableFieldInfos())) {
//            return R.error("无字段权限,无法预览数据");
//        }
        //hive查询结果的分页
//        List<String> columnList = tableInfo.getTableFieldInfos().stream().map(TableFieldInfo::getFieldName).collect(Collectors.toList());
        List<String> columnList = new ArrayList<>();
        //根据fieldId查询，字段名
        TableFieldInfo field = tableFieldInfoService.getById(fieldId);
        columnList.add(field.getFieldName());

        Map<String, Object> dataMap = hiveTableUtil.tableInfoDataPreviewPage(tableInfo, columnList, page, limit);

        List<JSONObject> list = JSON.parseArray(JSON.toJSONString(dataMap.get("data")), JSONObject.class);
        List<Map<String, Object>> dataList = new ArrayList<>();
        if (dataMap.get("data") != null) {

            //重组数据
            for (JSONObject data : list) {
                Map<String, Object> resMap = new HashMap<>();
                resMap.put("labelValue", data.get(field.getFieldName()));
                resMap.put("type", field.getFieldType());
                dataList.add(resMap);
            }
        }

        PageUtils pageData = new PageUtils(dataList, Long.parseLong(JSON.toJSONString(dataMap.get("totalCount"))), limit, page);
        R r = R.okWithPage(pageData);
        return r;
    }

    private R emptData(int limit, int page) {
        PageUtils pageData = new PageUtils(new ArrayList<>(), 0, limit, page);
        R r = R.okWithPage(pageData);
        //将标题也放进去
        r.put("titleList", new ArrayList<>());
        return r;
    }


    /**
     * 数据预览总条数
     */
    @ApiOperation("数据预览总条数")
    @GetMapping("/dataPreview/{id}")
    public R dataPreviewRowNum(@PathVariable("id") Integer id) throws Exception {
        TableInfo tableInfo = tableInfoService.getById(id);
        HiveTableUtil hiveTableUtil;
        if (StorageEngineEnum.KUDU.getCode().equals(tableInfo.getStoreEngine())) {
            hiveTableUtil = new HiveTableUtil(hiveConfig.getKuduJdbcUrl(), tableInfo.getDbName(), "hdfs", "hdfs");
        } else {
            hiveTableUtil = new HiveTableUtil(hiveConfig.getHiveserverurl(), tableInfo.getDbName(), "hdfs", "hdfs");
        }
        List<TableFieldInfo> tableFieldInfos = tableFieldInfoService.list(new QueryWrapper<TableFieldInfo>().eq("table_id", id));
        tableInfo.setTableFieldInfos(tableFieldInfos);
        if (CollectionUtil.isEmpty(tableFieldInfos)) {
            return emptMap(0L);
        }
        //查询总数
        Long totalCount = hiveTableUtil.dataPreviewRowNum(tableInfo);
        return emptMap(totalCount);
    }

    private R emptMap(Long i) {
        Map<String, Object> map = new HashMap<>();
        map.put("totalCount", i);
        return R.okWithData(map);
    }

    /**
     * 获取数据表的分区
     */
    @ApiOperation("获取数据表的分区")
//    @RequiresPermissions("bdp:tableInfo:dataPreview")
    @GetMapping("/partitions/{id}")
    public R partitions(@PathVariable("id") Integer id) {
        List<TableFieldInfo> infos = tableFieldInfoService.list(new QueryWrapper<TableFieldInfo>()
                .eq("table_id", id)
                .eq("is_partition", 1)
                .orderByAsc("field_order", "is_partition"));
        return R.okWithData(infos);
    }


    /**
     * 上传数据
     */
    @ApiOperation("上传文件")
    @SysLog(value="上传数据文件",type= OperationTypeEnum.UPLOADCODE,
            modulesType = OperationModulesEnum.TABLEMODELCODE,platformModuleType = ModuleEnum.DATA_MAP_MODULE_CODE)
    @PostMapping("/uploadFile")
    public R uploadFile(@ApiParam(value = "{'file':'file','partitions':'dt=20190101','tableId':1}")
                            @RequestParam(value = "file", required = false) MultipartFile file,
                        @RequestParam(value = "partitions",required = false) String partitions,
                        @RequestParam("tableId") Integer tableId,
                        @RequestParam(value = "writeType") Integer writeType,
                        @RequestParam(value = "flag", required = false) Integer flag
    ) {
        //writeType 1:覆盖  2:追加
        if (!tableInfoService.checkExistById(tableId)) {
            return R.error(DataDevelopmentBizExceptionEnum.TABLE_NOT_EXIST.getMessage());
        }
        if (file == null) {
            return R.error("您还没有选择要上传的文件");
        }
        //验证是否对这个表有权限操作
        TableInfo tableInfo = tableInfoService.getById(tableId);
        if (StorageEngineEnum.KUDU.getCode().equals(tableInfo.getStoreEngine())) {
            return R.error("kudu表不支持上传数据");
        }
        if (!YesOrNoEnum.YES.getValue().equals(flag)) {// 等于1 需要做权限校验
            if (!tableInfoService.checkPermission(tableInfo.getId())) {  //不是自己创建的数据 才做权限校验
                List<TableFieldInfo> tableFieldInfos = tableFieldInfoService.list(new QueryWrapper<>(), tableInfo.getId());
                if (CollectionUtil.isEmpty(tableFieldInfos)) {
                    throw new RRException("无字段权限对该表进行上传数据的操作！");
                }
                List<Integer> needUpdateTableFieldIds = tableFieldInfos.stream()
                        .map(TableFieldInfo::getId).collect(Collectors.toList());
                if (!dataPermissionService.checkApplyPermission(tableInfo.getId(), PermissionTypeEnum.UPDATE.getType())) {
                    if (!dataPermissionService.checkDataPermission(needUpdateTableFieldIds,
                            PermissionTypeEnum.STORE_FILED.getType(), PermissionTypeEnum.UPDATE.getType())) {
                        throw new RRException(DataDevelopmentBizExceptionEnum.UPDATE_FIELD_NO_PERMISSION.getMessage());
                    }
                }
            }
        }
        if (!file.isEmpty()) {
            String dbName = tableInfo.getDbName();
            String tableName = tableInfo.getTableName();
            HiveTableUtil hiveTableUtil = new HiveTableUtil(hiveConfig.getHiveserverurl(), dbName, "hdfs", "hdfs");
            HdfsUtil util = null;
            try {
                util = new HdfsUtil(bdpJobConfig);
                util.writeFile(file.getBytes(), HiveTableUtil.genTableLocation(dbName, tableName), partitions, file.getOriginalFilename(), writeType);
                hiveTableUtil.repairTable(tableName);
                hiveTableUtil.close();
            } catch (Exception e) {
                if(null != util){
                    util.close();
                }
                hiveTableUtil.close();
                throw new RRException(e.getMessage(), 500);
            }finally {
                if(null != util){
                    util.close();
                }
            }
            return R.ok().put("file", file.getOriginalFilename());
        } else {
            throw new RRException("文件为空!!!", 500);
        }
    }

    /**
     * 获取数据表的血缘关系
     */
    @ApiOperation("获取数据表的血缘关系")
    @SysLog(value = "获取数据表的血缘关系", type = OperationTypeEnum.SELECTCODE, modulesType = OperationModulesEnum.TABLEMODELCODE,platformModuleType = ModuleEnum.DATA_MAP_MODULE_CODE)
    @GetMapping("/bloodRelation/{id}")
    public R bloodRelation(@PathVariable("id") Integer id) {
        List<TableRelation> parents = tableRelationService.list(new QueryWrapper<TableRelation>().eq("cid", id));
        List<TableRelation> childs = tableRelationService.list(new QueryWrapper<TableRelation>().eq("pid", id));

        JSONArray parray = new JSONArray();
        JSONObject nowJson = new JSONObject();
        nowJson.put("name", tableInfoService.getById(id).getTableName());
        nowJson.put("type", 2);
        parray.add(nowJson);
        for (TableRelation pTable : parents) {
            TableInfo pInfo = tableInfoService.getById(pTable.getPid());
            if (pInfo != null) {
                JSONObject pJson = new JSONObject();
                pJson.put("name", pInfo.getTableName());
                pJson.put("type", 1);
                parray.add(pJson);
            }
        }
        for (TableRelation cTable : childs) {
            TableInfo cInfo = tableInfoService.getById(cTable.getCid());
            if (cInfo != null) {
                JSONObject tableObj = new JSONObject();
                tableObj.put("name", cInfo.getTableName());
                tableObj.put("type", 3);
                parray.add(tableObj);
            }
        }
        return R.okWithPage(parray);
    }

    /**
     * 获取数据表的血缘关系
     */
    @ApiOperation("获取数据表的血缘关系")
    @SysLog(value = "获取数据表的血缘关系", type = OperationTypeEnum.SELECTCODE, modulesType = OperationModulesEnum.TABLEMODELCODE,platformModuleType = ModuleEnum.DATA_MAP_MODULE_CODE)
    @GetMapping("/bloodRelation2/{id}")
    public DataRes<TableRelationshipRes> bloodRelation2(@PathVariable("id") Integer id) {
        TableRelationshipRes res = tableRelationshipService.bloodRelation(id);

        return BaseRes.okWithData(res);
    }

    /**
     * 上传字段的csv文件以逗号隔开fieldName,fieldType,fieldAlias,isPartition
     * 返回：{"fieldName":"","fieldType":"","fieldAlias":"","isPartition":0,"fieldOrder":""}
     */
    @ApiOperation("上传字段")
    @SysLog(value = "上传字段", type = OperationTypeEnum.UPLOADCODE, modulesType = OperationModulesEnum.TABLEMODELCODE
            ,platformModuleType = ModuleEnum.DATA_MAP_MODULE_CODE)

    @PostMapping("/uploadField")

    public R uploadField(@RequestParam(value = "file", required = false) MultipartFile multipartFile) {
        if (multipartFile == null) {
            return R.error("请选择要上传的文件");
        }
        JSONArray jsonArray = new JSONArray();
        if (!multipartFile.isEmpty()) {
            try {
                File file = File.createTempFile("tmp", null);
                multipartFile.transferTo(file);
                file.deleteOnExit();
                if (multipartFile.getOriginalFilename().contains(".csv")) {
                    readFiledForCsv(file, jsonArray);
                }
            }catch (RRException e){
                return R.error(e.getMsg());
            }
            catch (Exception e) {
                return R.error("请按照模板格式修改上传文件");
            }
            return R.okWithData(jsonArray);
        } else {
            return R.error("文件为空");
        }
    }


    public void readFiledForCsv(File file, JSONArray jsonArray) {
        // file.getBytes()
        CsvReader reader = CsvUtil.getReader();
        // 从文件中读取CSV数据
        CsvData data = reader.read(file, Charset.forName("GBK"));
        List<CsvRow> rows = data.getRows();
        if (rows != null && rows.size() >= 2) {
            //遍历行
            for (int i = 1; i < rows.size(); i++) {
                for (int j = 0; j < 4; j++) {
                    if (null == rows.get(i).get(j) || "".equals(rows.get(i).get(j))) {
                        throw new RRException(String.format("表格中  '%s'  存在空数据", TableDataHeaderType.ObjOf(j).getDesc()));
                    }
                }
                //getRawList返回一个List列表，列表的每一项为CSV中的一个单元格（既逗号分隔部分）
                JSONObject jObject = new JSONObject();
                jObject.put(TableDataHeaderType.fieldName.getName(), rows.get(i).get(TableDataHeaderType.fieldName.getCode()));
                if (!TableDataType.containsName(rows.get(i).get(TableDataHeaderType.fieldType.getCode()))) {
                    throw new RRException(String.format("字段名为%s的字段类型不合规", rows.get(i).get(TableDataHeaderType.fieldName.getCode())));
                }
                String type = rows.get(i).get(TableDataHeaderType.fieldType.getCode());
                type = type != null ? type.toUpperCase() : "STRING";
                jObject.put(TableDataHeaderType.fieldType.getName(), type);
                jObject.put(TableDataHeaderType.fieldAlias.getName(), rows.get(i).get(TableDataHeaderType.fieldAlias.getCode()));
                jObject.put(TableDataHeaderType.isPartition.getName(), Integer.parseInt(rows.get(i).get(TableDataHeaderType.isPartition.getCode())));
                jObject.put(TableDataHeaderType.fieldOrder.getName(), "");
                jsonArray.add(jObject);
            }
        }

    }

    @ApiOperation("下载模版")
//    @SysLog("下载模版")
    @SysLog(value = "下载模板", type = OperationTypeEnum.DOWNLOADCODE, modulesType = OperationModulesEnum.TABLEMODELCODE,platformModuleType = ModuleEnum.DATA_MAP_MODULE_CODE)
    @PostMapping("/downloadField")
    public void downloadField(HttpServletResponse response) throws Exception {
        response.reset();
        String fileName = String.format("field_data.csv");
        response.setHeader("Content-Disposition", "attachment;filename=" + fileName);
        response.setHeader("filename", fileName);
        OutputStream outputStream = response.getOutputStream();
        String header = String.format("%s,%s,%s,%s", TableDataHeaderType.fieldName.getDesc(), TableDataHeaderType.fieldType.getDesc(), TableDataHeaderType.fieldAlias.getDesc(), TableDataHeaderType.isPartition.getDesc());
        outputStream.write(header.getBytes("GBK"));
        outputStream.close();
    }

}
